package org.spdata.tsdb.coder;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.spdata.utils.ByteUtils;
import org.spdata.utils.ListUtils;

/**
 * 对整数进行编码压缩，主要针对状态量，特点是：大部分值为0、1,所有值都只用一个byte表示
 */
public class IntArrayCoder {
	public byte[] encode(int[] input) {
		
		//按重复情况整理成sections
		List<Map<String,Object>> sections = new ArrayList<Map<String,Object>>();	
		
		//其他连续重复的值所在序号
		List<Integer> other  = new ArrayList<Integer>();
		
		Integer rpValue = null;
		Integer from = null;
		Integer end = null;
		for(int i=0;i<input.length;i++) {
			int v = input[i];
			if(rpValue==null) {
				rpValue = v;
				from = i;
				end = i;
			}else if(v == rpValue.intValue()) {
				end = i;
			}else {
				if(end-from>5) {
					Map<String,Object> section= new HashMap<String,Object>();
					section.put("from",from);
					section.put("end", end);
					section.put("value", rpValue);
					sections.add(section);
				}else {
					for(int j=from;j<=end;j++){
						other.add(j);
					}
				}
				
				rpValue = v;
				from = i;
				end = i;
			}
		}
		if(end-from>5) {
			Map<String,Object> section= new HashMap<String,Object>();
			section.put("from",from);
			section.put("end", end);
			section.put("value", rpValue);
			sections.add(section);
		}else {
			for(int j=from;j<=end;j++){
				other.add(j);
			}
		}
		
		
		//对sections编码
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		output.write(sections.size());
		for(Map<String,Object> section:sections) {
			from = (Integer)section.get("from");
			end = (Integer)section.get("end");
			Integer value = (Integer)section.get("value");
			output.write(value);
			output.write(ByteUtils.changeIntTo2Bytes(from),0,2);
			output.write(ByteUtils.changeIntTo2Bytes(end),0,2);
		}
		//对other进行编码
		for(Integer index : other) {
			int value = input[index];
			output.write(value);
		}
		
		return output.toByteArray();
	}
	
	public int[] decode(byte[] input) {
		List<Integer> values = new ArrayList<Integer>();
		int index = 0;
		int secionsCount = 0x7FFF & input[index++]; ;
		for(int i=0;i<secionsCount;i++) {
			int value = input[index++];
			int from = ByteUtils.changeBytesToInt(input[index++],input[index++]);
			int end = ByteUtils.changeBytesToInt(input[index++],input[index++]);
			ListUtils.expandList(values, end);
			for(int j=from;j<=end;j++) {
				values.set(j, value);
			}
		}
		int from = 0;
		while(index<input.length) {
			int v = input[index++];
			ListUtils.findNullAndSetValue(values, from, v);
		}
		
		
		int[] result = ListUtils.toIntArr(values);
		return result;
	}
	
	public static void main(String[] args) {
		test1();
		//test0();
	}
	
	public static void test1() {
		IntArrayCoder coder = new IntArrayCoder();
		int[] values = new int[3600];
		for(int i=0;i<3600;i++) {
			if(i>100 && i<120) {
				values[i] = 10;
			}else if(i>200 && i<230) {
				values[i] = 7;
			}else
				values[i] = i/1000;
		}
		
		byte[] encoded = coder.encode(values);
		System.out.println("编码后的数据：");
		System.out.println(ByteUtils.changeBytesToHexStr(encoded));
		
		int[] decoded = coder.decode(encoded);
		//和原始数据比对
		int count = 0;
		for(int i=0;i<720;i++) {
			if(values[i]!=decoded[i]) {
				System.out.println("第"+i+"个数据不对了");
				count ++;
			}
		}
		System.out.println("解码后的数据：");
		System.out.println(NumberSeqFormatter.toString(decoded));
		System.out.println("共有"+count+"个数据不对");
	}
	
	public static void test0() {
		IntArrayCoder coder = new IntArrayCoder();
		int[] values = new int[3600];
		for(int i=0;i<3600;i++) {
			values[i] = i/1000;
		}
		
		byte[] encoded = coder.encode(values);
		System.out.println("编码后的数据：");
		System.out.println(ByteUtils.changeBytesToHexStr(encoded));
		
		int[] decoded = coder.decode(encoded);
		//和原始数据比对
		int count = 0;
		for(int i=0;i<720;i++) {
			if(values[i]!=decoded[i]) {
				System.out.println("第"+i+"个数据不对了");
				count ++;
			}
		}
		System.out.println("解码后的数据：");
		System.out.println(NumberSeqFormatter.toString(decoded));
		System.out.println("共有"+count+"个数据不对");
	}
}
